package cn.touna.jss.modules.callback.controller;

import cn.touna.jss.common.aspect.entity.CacheCreditQueryRequest;
import cn.touna.jss.common.cache.HbaseComponent;
import cn.touna.jss.common.entity.CreditQueryRequest;
import cn.touna.jss.common.mq.KafkaComponent;
import cn.touna.jss.common.properties.disconf.JuXinLiProperties;
import cn.touna.jss.common.util.CommonUtils;
import cn.touna.jss.common.util.IPUtil;
import cn.touna.jss.common.util.JssConstant;
import cn.touna.jss.modules.callback.entity.JuxinliCallback;
import cn.touna.jss.modules.callback.entity.JuxinliEntiry;
import cn.touna.jss.modules.callback.service.ExtCallBackService;
import cn.touna.risk.api.domain.Response;
import cn.touna.risk.api.enums.IntfTypeEnum;
import cn.touna.risk.api.enums.SystemErrorCodeEnum;
import cn.touna.risk.api.utils.ServiceContext;
import cn.touna.risk.cache.redis.RedisCache;
import cn.touna.risk.threadpool.common.util.ThreadPoolUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.squareup.okhttp.OkHttpClient;
import com.squareup.okhttp.Request;
import org.apache.commons.io.FileUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.util.Date;


@RestController
public class JxlCallbackController {

    private static final Logger logger = LogManager.getLogger(JxlCallbackController.class);

    @Autowired
    private HbaseComponent hbaseComponent;

    @Resource
    private RedisCache redisCache;

    @Autowired
    ExtCallBackService extCallBackService;

    @Autowired
    private KafkaComponent kafkaComponent;

    @Autowired
    private JuXinLiProperties jxlProperties;

    private static final long oneMin = 1000 * 60;

    /**
     * 聚信立报告回调接口
     *
     * @param request
     * @return
     */
    @RequestMapping(value = "/crs/callBackJxlReport", method = {RequestMethod.POST})
    public JSONObject callBackJxlReport(HttpServletRequest request) {
        JSONObject result = new JSONObject();
        try {
            String ip = IPUtil.getClientIP(request);
            logger.info("REQ【聚信立报告回调】callBackJxlReport-访问ip地址: {}", ip);
            long currtTime = System.currentTimeMillis();
            String str = redisCache.get(ip);
            if (str == null) {
                redisCache.set(ip, currtTime + "_" + 1);
            } else {
                //时间戳
                long start = Long.valueOf((str.split("_")[0]));
                //次数
                int time = Integer.valueOf(str.split("_")[1]);
                long endTime = System.currentTimeMillis();
                int useTime = Integer.valueOf((int) (endTime - start));
                if (useTime < oneMin) {
                    if (time > 30) {
                        logger.info("REQ【聚信立报告回调】callBackJxlReport-一分钟内超过访问次数: {}", time);
                        result.put("code", "400");
                        result.put("node", "超过访问次数");
                        return result;
                    } else {
                        redisCache.set(ip, currtTime + "_" + (time + 1));
                    }
                } else {
                    redisCache.set(ip, currtTime + "_" + 1);
                }
            }
            String paramString = request.getParameter("data");
            logger.info("REQ【聚信立报告回调】DataReportController-请求信息: {}", paramString);
            if (CommonUtils.isEmpty(paramString)) {
                result.put("code", "400");
                result.put("node", "超过访问次数");
                return result;
            }
            return callBackJxlReport(paramString);

        } catch (Exception e) {
            logger.error("PRO 调用【聚信立报告回调-callBackJxlReportData】异常, msg:{}", e.getMessage());
            result.put("code", "400");
            result.put("node", "解析异常");
            return result;
        }
    }

    public JSONObject callBackJxlReport(String paramString) throws Exception {
        logger.info("PRO 调用【聚信立报告回调-callBackJxlReportData】jxlParams:{}", paramString);
        JSONObject result = new JSONObject();
        JSONObject paramJson = JSON.parseObject(paramString);
        String name = (String) paramJson.get("CUST_NAME");
        String mobile = (String) paramJson.get("APP_PHONE_NO");
        String idCard = (String) paramJson.get("APP_IDCARD_NO");
        JSONObject reportInfo = (JSONObject) paramJson.get("JSON_INFO");
        paramJson.put("report_data", reportInfo);
        if (CommonUtils.isEmpty(reportInfo) || CommonUtils.isEmpty(name) || CommonUtils.isEmpty(mobile) || CommonUtils.isEmpty(idCard)) {
            result.put("code", "400");
            result.put("node", "参数校验为空");
            return result;
        }
        JuxinliEntiry juxinliEntiry = buildJuxinliEntity(paramJson);
        CreditQueryRequest creditQueryRequest = juxinliEntiry.getRequest();
        Response jxlResponse = juxinliEntiry.getJxlResponse();
        CacheCreditQueryRequest cacheCreditQueryRequest = juxinliEntiry.getCacheCreditQueryRequest();
        kafkaComponent.sendSyncCallData(creditQueryRequest, jxlResponse);
        hbaseComponent.saveCreditResponseToCache(cacheCreditQueryRequest, jxlResponse);
        logger.info("PRO 调用【聚信立报告回调-callBackJxlReportData】发送kafka写入hbase request:{},reponse:{}", JSONObject.toJSON(creditQueryRequest), JSONObject.toJSON(jxlResponse));
        ThreadPoolUtil.submit(JssConstant.JSS_POOL_NAME, this, "getAccessRawData", juxinliEntiry.getJuxinliCallback(), cacheCreditQueryRequest);
        extCallBackService.saveJxlCallbackHistory(juxinliEntiry.getJuxinliCallback());
        paramJson.put("success", "true");
        paramJson.put("note", "报告获取成功");
        result.put("code", "200");
        result.put("node", "接收成功");
        return result;
    }


    /**
     * 构建聚信立参数
     *
     * @param paramJson
     * @return
     */
    private JuxinliEntiry buildJuxinliEntity(JSONObject paramJson) {
        JuxinliEntiry juxinliEntiry = new JuxinliEntiry();
        String name = (String) paramJson.get("CUST_NAME");
        String mobile = (String) paramJson.get("APP_PHONE_NO");
        String idCard = (String) paramJson.get("APP_IDCARD_NO");
        JSONObject reportInfo = (JSONObject) paramJson.get("JSON_INFO");
        paramJson.put("report_data", reportInfo);
        paramJson.remove("CUST_NAME");
        paramJson.remove("APP_PHONE_NO");
        paramJson.remove("APP_IDCARD_NO");
        paramJson.remove("JSON_INFO");
        paramJson.put("success", "true");
        paramJson.put("note", "报告获取成功");

        CreditQueryRequest request = new CreditQueryRequest();
        request.setCrNo(ServiceContext.genUniqueId());
        request.setIdCard(idCard);
        request.setMobile(mobile);
        JSONObject param = new JSONObject();
        param.put("idCard", idCard);
        param.put("mobile", mobile);
        request.setParams(param);
        request.setMethod(IntfTypeEnum.JXL_REPORT_DATA.getCode());
        //返回结果
        Response jxlResponse = new Response().success(SystemErrorCodeEnum.SYSTEM_REQUEST_SUCC, paramJson.toString());
        CacheCreditQueryRequest cacheCreditQueryRequest = new CacheCreditQueryRequest();
        cacheCreditQueryRequest.setCrNo(ServiceContext.genUniqueId());
        cacheCreditQueryRequest.setIdCard(idCard);
        cacheCreditQueryRequest.setMobile(mobile);
        cacheCreditQueryRequest.setCacheStrategy("Default");
        cacheCreditQueryRequest.setParams(param);
        cacheCreditQueryRequest.setMethod(IntfTypeEnum.JXL_REPORT_DATA.getCode());
        cacheCreditQueryRequest.setQueryTime(new Date());

        JuxinliCallback juxinliCallback = new JuxinliCallback();
        juxinliCallback.setBizType(request.getBizType());
        juxinliCallback.setIdNo(idCard);
        juxinliCallback.setMobile(mobile);
        juxinliCallback.setName(name);
        juxinliCallback.setTaskId(request.getCrNo());

        juxinliEntiry.setJuxinliCallback(juxinliCallback);
        juxinliEntiry.setJxlResponse(jxlResponse);
        juxinliEntiry.setRequest(request);
        juxinliEntiry.setCacheCreditQueryRequest(cacheCreditQueryRequest);
        return juxinliEntiry;
    }


    /**
     * 获取聚信立源数据
     *
     * @param juxinliCallback
     * @return
     * @throws Exception
     */
    public void getAccessRawData(JuxinliCallback juxinliCallback, CacheCreditQueryRequest cacheCreditQueryRequest) throws Exception {
        StringBuilder url = new StringBuilder(jxlProperties.getAccessRawDataUrl());
        url.append("?access_token=").append(getToken());
        url.append("&name=").append(juxinliCallback.getName());
        url.append("&phone=").append(juxinliCallback.getMobile());
        url.append("&client_secret=").append(jxlProperties.getClientSecret());
        url.append("&idcard=").append(juxinliCallback.getIdNo());
        logger.info("【getAccessRawData请求参数】 crNo:{}, idcard{},mobile:{},requrl:{}", juxinliCallback.getTaskId(), juxinliCallback.getIdNo(), juxinliCallback.getMobile(), url.toString());
        String result = getData(url.toString());
        JSONObject jsonObject = JSONObject.parseObject(result);
        String dataResult = (String) jsonObject.get("success");
        logger.info("【getAccessRawData返回结果】crNo:{}, idcard{},mobile:{},result:{}",juxinliCallback.getTaskId(), juxinliCallback.getIdNo(), juxinliCallback.getMobile(), result);
        if ("true".equals(dataResult)) {
            cacheCreditQueryRequest.setMethod("JuXinLi.getAccessRawData");
            Response jxlResponse = new Response().success(SystemErrorCodeEnum.SYSTEM_REQUEST_SUCC, jsonObject);
            hbaseComponent.saveCreditResponseToCache(cacheCreditQueryRequest, jxlResponse);
            logger.info("PRO 调用【聚信立源数据获取-getAccessRawData】写入hbase request:{},reponse:{}", JSONObject.toJSON(cacheCreditQueryRequest), JSONObject.toJSON(jxlResponse));
        }
    }


    /**
     * 获取token
     *
     * @param tokenMsg
     * @return
     */
    public String getAccessToken(String tokenMsg) {
        int begin = tokenMsg.indexOf("access_token");
        int end = tokenMsg.indexOf("note");
        String token = tokenMsg.substring(begin + 15, end - 3);
        logger.info("AccessToken is: {}", token);
        return token;
    }


    /**
     * 权限分配类接口,获得安全凭证码
     *
     * @return
     * @throws Exception
     */
    private String getAccessReportToken() throws Exception {
        StringBuffer url = new StringBuffer(jxlProperties.getAccessTokenReportUrl());
        url.append("?client_secret=").append(jxlProperties.getClientSecret())
                .append("&hours=").append(jxlProperties.getHours()).append("&org_name=").append(jxlProperties.getOrgName()); //拼接url
        String message = "get access report token ";
        String result = getData(url.toString());
        return result;
    }


    /**
     * 根据不用的url， 使用 get方法获取数据
     *
     * @param url
     * @param message
     * @return
     * @throws Exception
     */
    private String getData(String url) throws Exception {
        //记录日志
        logger.info("请求为 : {}", url);
        OkHttpClient client = new OkHttpClient();
        Request request = new Request.Builder().url(url).build();
        String result = client.newCall(request).execute().body().string();
        logger.info( "返回结果为: {}", result);
        return result;
    }


    /**
     * 获取Token
     *
     * @return
     */
    private String getToken() {
        String accessToken = "";
        // 获取安全凭证码
        try {
            String tokenRes = getAccessReportToken();
            accessToken = getAccessToken(tokenRes);
        } catch (Exception e) {
            logger.error("获取安全凭证码失败异常：{}", e);
        }
        return accessToken;
    }


    public static void main(String[] args) {
        try {
            JxlCallbackController jxl = new JxlCallbackController();
            String content = FileUtils.readFileToString(new File("E:\\jxlcallback.txt"), "UTF-8");
            JSONObject jsonObject = jxl.callBackJxlReport(content);
            System.out.println(jsonObject);
        } catch (Exception e) {
            e.printStackTrace();
        }

    }


}